﻿// ---------------------------------------------------------------------------

#pragma hdrstop

#include "BFIExpression.h"
#include "Unit1.h"

// ---------------------------------------------------------------------------

#pragma package(smart_init)
map<String, String>BFIExpression::keys;

int BFIExpression::border;

BFIExpression::BFIExpression(TImage* Image, TScrollBox* ScrollBox) {
        this->image = Image;
        this->scrollBox = ScrollBox;
        this->lastIsOperation = true;

        this->keys["and"] = "BFIAND";
        this->keys["conv_implication"] = "BFIConvImplication";
        this->keys["empty_set"] = "BFIEmptySet";
        this->keys["implication"] = "BFIImplication";
        this->keys["or"] = "BFIOR";
        this->keys["pirs"] = "BFIPirs";
        this->keys["text_symbol"] = "BFITextSymbol";
        this->keys["xor"] = "BFIXOR";

        // vectorNew = new Characters;
        rulesRoots = new RulesRootsMap;

        this->init();
        this->initRules();

        this->priorities.push_back("implication");
        this->priorities.push_back("~");
        this->priorities.push_back("xor");
        this->priorities.push_back("conv_implication");
        this->priorities.push_back("|");
        this->priorities.push_back("pirs");

}

bool BFIExpression::keyIsCharacter(String key) {
        return key == "text_symbol";
}

void BFIExpression::addByKey(String key, bool isInversed, String Character,
        bool add) {
        if (true /* !this->lastIsOperation */ && keys.count(key)) {
                BFISymbol* symbol = BFISymbolsFactory::getSymbol(key,
                        this->image->Canvas, isInversed
                        /* this->image->Canvas->Font->Size */);
                if (this->keyIsCharacter(key)) {
                        BFITextSymbol* textSymbol = (BFITextSymbol*)symbol;
                        textSymbol->setSymbol(Character);
                        symbol = textSymbol;
                        key = textSymbol->getSymbol();
                }
                this->draw(symbol);
                if (add) {
                        BooleanCharacter* bChar = new BooleanCharacter();
                        bChar->inversion = isInversed;
                        bChar->x = this->x;
                        bChar->y = this->y;
                        bChar->key = key;
                        this->characters.push_back(bChar);
                }
                // this->symbols.push_back(key);
        }
        else
                this->showError();
}

void BFIExpression::addAND(bool isInversed) {
        String key = "and";
        this->addByKey(key, isInversed);
}

void BFIExpression::addOR(bool isInversed) {
        String key = "or";
        this->addByKey(key, isInversed);
}

void BFIExpression::addNOR(bool isInversed) {
        String key = "nor";
        this->addByKey(key, isInversed);
}

void BFIExpression::addXOR(bool isInversed) {
        String key = "xor";
        this->addByKey(key, isInversed);
}

void BFIExpression::addSymbol(char Character, bool isInversed) {
        String key = "text_symbol";
        this->addByKey(key, isInversed, Character);
}

void BFIExpression::addShefferStroke(bool isInversed) {
        String key = "text_symbol";
        this->addByKey(key, isInversed, '|');
}

void BFIExpression::addEquivalence(bool isInversed) {
        String key = "text_symbol";
        this->addByKey(key, isInversed, '~');
}

void BFIExpression::addUniversum(bool isInversed) {
        String key = "text_symbol";
        this->addByKey(key, isInversed, 'U');
}

void BFIExpression::addImplication(bool isInversed) {
        String key = "implication";
        this->addByKey(key, isInversed);
}

void BFIExpression::addConvImplication(bool isInversed) {
        String key = "conv_implication";
        this->addByKey(key, isInversed);
}

void BFIExpression::addPirs(bool isInversed) {
        String key = "pirs";
        this->addByKey(key, isInversed);
}

void BFIExpression::addEmptySet(bool isInversed) {
        String key = "empty_set";
        this->addByKey(key, isInversed);
}

void BFIExpression::showError() {
        ShowMessage("Íåâ³ðíå ñèíòàêñè÷íå çàïîâíåííÿ");
}

map<String, String>BFIExpression::getKeys() {
        return keys;
}

void BFIExpression::draw(BFISymbol* Character) {
        int fontSize = image->Canvas->Font->Size;
        // int border = fontSize/2;
        int width = Character->width();
        // ShowMessage(IntToStr(width));
        if (x + width + image->Canvas->Font->Size + border > image->Width) {
                x = border * 2;
                y += image->Canvas->Font->Size * 2;
                if (y + 2 * border + image->Canvas->Font->Size * 2 > image->Height) {
                        image->Height = y + 2 * border + image->Canvas->Font->Size * 2;
                        image->Picture->Bitmap->Height = image->Height;
                        scrollBox->VertScrollBar->Position = image->Height;
                }
        }
        Character->draw(x, y);
        if (Character->isInversed()) {
                image->Canvas->MoveTo(x - 1, y);
                image->Canvas->LineTo(x + width + fontSize / 5, y);
        }
        // Image1->Canvas->TextOutW(x,y,Key);
        x += width + fontSize / 5;

}

void BFIExpression::setXY(int x, int y) {
        this->x = x;
        this->y = y;
}

int BFIExpression::getX() {
        return this->x;
}

void BFIExpression::init() {
        image->Height = scrollBox->Height - 5;
        border = this->image->Canvas->Font->Size / 2;
        this->setXY(border*2, border);
}

void BFIExpression::initRules() {
        BooleanCharacter* openBracket = new BooleanCharacter();
        openBracket->inversion = false;
        openBracket->key = "(";
        BooleanCharacter* closeBracket = new BooleanCharacter();
        closeBracket->inversion = false;
        closeBracket->key = ")";
        BooleanCharacter* notOpenBracket = new BooleanCharacter();
        notOpenBracket->inversion = true;
        notOpenBracket->key = "(";
        BooleanCharacter* notCloseBracket = new BooleanCharacter();
        notCloseBracket->inversion = true;
        notCloseBracket->key = ")";
        BooleanCharacter* A = new BooleanCharacter();
        A->inversion = false;
        A->key = "A";
        BooleanCharacter* B = new BooleanCharacter();
        B->inversion = false;
        B->key = "B";
        BooleanCharacter* C = new BooleanCharacter();
        C->inversion = false;
        C->key = "C";
        BooleanCharacter* notA = new BooleanCharacter();
        notA->inversion = true;
        notA->key = "A";
        BooleanCharacter* notB = new BooleanCharacter();
        notB->inversion = true;
        notB->key = "B";
        BooleanCharacter* notC = new BooleanCharacter();
        notC->inversion = true;
        notC->key = "C";
        BooleanCharacter* empty = new BooleanCharacter();
        empty->inversion = false;
        empty->key = "empty_set";
        BooleanCharacter* notEmpty = new BooleanCharacter();
        notEmpty->inversion = true;
        notEmpty->key = "empty_set";
        BooleanCharacter* universum = new BooleanCharacter();
        universum->inversion = false;
        universum->key = "U";
        BooleanCharacter* notUniversum = new BooleanCharacter();
        notUniversum->inversion = true;
        notUniversum->key = "U";
        BooleanCharacter* and = new BooleanCharacter();
        and->inversion = false;
        and->key = "and";
        BooleanCharacter* notAnd = new BooleanCharacter();
        notAnd->inversion = true;
        notAnd->key = "and";
        BooleanCharacter* or = new BooleanCharacter();
        or->inversion = false;
        or->key = "or";
        BooleanCharacter* notOr = new BooleanCharacter();
        notOr->inversion = true;
        notOr->key = "or";

        Characters* implication = new Characters;
        implication->push_back(notA);
        implication->push_back(or);
        implication->push_back(B);

        Characters* equivalence = new Characters;
        equivalence->push_back(A);
        equivalence->push_back(and);
        equivalence->push_back(B);
        equivalence->push_back(or);
        equivalence->push_back(notA);
        equivalence->push_back(and);
        equivalence->push_back(notB);

        Characters* xor = new Characters;
        xor->push_back(A);
        xor->push_back(and);
        xor->push_back(notB);
        xor->push_back(or);
        xor->push_back(notA);
        xor->push_back(and);
        xor->push_back(B);

        Characters* conv_implication = new Characters;
        conv_implication->push_back(A);
        conv_implication->push_back(or);
        conv_implication->push_back(notB);

        Characters* pirs = new Characters;
        pirs->push_back(notA);
        pirs->push_back(and);
        pirs->push_back(notB);

        Characters* sheffer = new Characters;
        sheffer->push_back(notA);
        sheffer->push_back(or);
        sheffer->push_back(notB);

        this->changes["implication"] = implication;
        this->changes["~"] = equivalence;
        this->changes["xor"] = xor;
        this->changes["conv_implication"] = conv_implication;
        this->changes["pirs"] = pirs;
        this->changes["|"] = sheffer;

        Characters* rule1 = new Characters;
        rule1->push_back(notUniversum);
        Characters* rule1Result = new Characters;
        rule1Result->push_back(empty);

        Characters* rule2 = new Characters;
        rule2->push_back(notEmpty);
        Characters* rule2Result = new Characters;
        rule2Result->push_back(universum);

        Characters* rule3 = new Characters;
        rule3->push_back(A);
        rule3->push_back(or);
        rule3->push_back(empty);
        Characters* rule3Result = new Characters;
        rule3Result->push_back(A);

        Characters* rule4 = new Characters;
        rule4->push_back(A);
        rule4->push_back(and);
        rule4->push_back(empty);
        Characters* rule4Result = new Characters;
        rule4Result->push_back(empty);

        Characters* rule5 = new Characters;
        rule5->push_back(A);
        rule5->push_back(or);
        rule5->push_back(universum);
        Characters* rule5Result = new Characters;
        rule5Result->push_back(universum);

        Characters* rule6 = new Characters;
        rule6->push_back(A);
        rule6->push_back(and);
        rule6->push_back(universum);
        Characters* rule6Result = new Characters;
        rule6Result->push_back(A);

        Characters* rule7 = new Characters;
        rule7->push_back(A);
        rule7->push_back(or);
        rule7->push_back(notA);
        Characters* rule7Result = new Characters;
        rule7Result->push_back(universum);

        Characters* rule8 = new Characters;
        rule8->push_back(A);
        rule8->push_back(and);
        rule8->push_back(notA);
        Characters* rule8Result = new Characters;
        rule8Result->push_back(empty);

        Characters* rule9 = new Characters;
        rule9->push_back(A);
        rule9->push_back(or);
        rule9->push_back(A);
        Characters* rule9Result = new Characters;
        rule9Result->push_back(A);

        Characters* rule10 = new Characters;
        rule10->push_back(A);
        rule10->push_back(and);
        rule10->push_back(A);
        Characters* rule10Result = new Characters;
        rule10Result->push_back(A);

        Characters* rule11 = new Characters;
        rule11->push_back(A);
        rule11->push_back(and);
        rule11->push_back(openBracket);
        rule11->push_back(A);
        rule11->push_back(or);
        rule11->push_back(B);
        rule11->push_back(closeBracket);
        Characters* rule11Result = new Characters;
        rule11Result->push_back(A);

        Characters* rule12 = new Characters;
        rule12->push_back(A);
        rule12->push_back(and);
		rule12->push_back(B);
		rule12->push_back(or);
		rule12->push_back(A);
		Characters* rule12Result = new Characters;
        rule12Result->push_back(A);

        Characters* rule13 = new Characters;
        rule13->push_back(openBracket);
        rule13->push_back(A);
        rule13->push_back(or);
        rule13->push_back(B);
        rule13->push_back(closeBracket);
        rule13->push_back(and);
        rule13->push_back(C);
        Characters* rule13Result = new Characters;
        rule13Result->push_back(A);
        rule13Result->push_back(and);
        rule13Result->push_back(C);
        rule13Result->push_back(or);
        rule13Result->push_back(B);
        rule13Result->push_back(and);
        rule13Result->push_back(C);

        Characters* rule14 = new Characters;
        rule14->push_back(A);
        rule14->push_back(or);
        rule14->push_back(openBracket);
        rule14->push_back(B);
        rule14->push_back(and);
        rule14->push_back(C);
        rule14->push_back(closeBracket);
        Characters* rule14Result = new Characters;
        rule14Result->push_back(openBracket);
        rule14Result->push_back(A);
        rule14Result->push_back(or);
        rule14Result->push_back(B);
        rule14Result->push_back(closeBracket);
        rule14Result->push_back(and);
        rule14Result->push_back(openBracket);
        rule14Result->push_back(A);
        rule14Result->push_back(or);
        rule14Result->push_back(C);
        rule14Result->push_back(closeBracket);

        Characters* rule15 = new Characters;
        rule15->push_back(A);
        rule15->push_back(or);
        rule15->push_back(B);
        rule15->push_back(or);
        rule15->push_back(A);
        Characters* rule15Result = new Characters;
        rule15Result->push_back(A);
        rule15Result->push_back(or);
        rule15Result->push_back(B);

        Characters* rule16 = new Characters;
        rule16->push_back(A);
        rule16->push_back(and);
        rule16->push_back(B);
        rule16->push_back(and);
        rule16->push_back(A);
        Characters* rule16Result = new Characters;
        rule16Result->push_back(A);
        rule16Result->push_back(and);
        rule16Result->push_back(B);

        // rules = new Rules;

        // rules->clear();

        // (rules)[&rule1] = &rule1Result;
        // (rules)[&rule2] = &rule2Result;
        // (rules)[&rule3] = &rule3Result;
        // (rules)[&rule4] = &rule4Result;
        // (rules)[&rule5] = &rule5Result;
        // (rules)[&rule6] = &rule6Result;
        // (rules)[&rule7] = &rule7Result;
        // (rules)[&rule8] = &rule8Result;
        // (rules)[&rule9] = &rule9Result;
        // (rules)[&rule10] = &rule10Result;
        // (rules)[&rule11] = &rule11Result;
        // (rules)[&rule12] = &rule12Result;
        // (rules)[&rule13] = &rule13Result;
        // (rules)[&rule14] = &rule14Result;

        // this->processRules(rule1, rule1Result);
        this->processRules(rule1, rule1Result);
        // delete rule1;
        // delete rule1Result;
        this->processRules(rule2, rule2Result);
        // delete rule2;
        // delete rule2Result;
        this->processRules(rule3, rule3Result);
        // delete rule3;
        // delete rule3Result;
        this->processRules(rule4, rule4Result);
        // delete rule4;
        // delete rule4Result;
        this->processRules(rule5, rule5Result);
        // delete rule5;
        // delete rule5Result;
        this->processRules(rule6, rule6Result);
        // delete rule6;
        // delete rule6Result;
        this->processRules(rule7, rule7Result);
        // delete rule7;
        // delete rule7Result;
        this->processRules(rule8, rule8Result);
        // delete rule8;
        // delete rule8Result;
        this->processRules(rule9, rule9Result);
        this->processRules(rule10, rule10Result);
        // delete rule10;
        // delete rule10Result;
        //
        this->processRules(rule11, rule11Result);
        this->processRules(rule12, rule12Result);
        this->processRules(rule13, rule13Result);
        this->processRules(rule14, rule14Result);
        this->processRules(rule15, rule15Result);
        this->processRules(rule16, rule16Result);

        // rulesRoots = new RulesRootsMap;

        // rulesRoots->clear();

        // int i = 0;
        //
        // for (iRules rIter = rules.begin(); rIter != rules.end(); rIter++) {
        // i++;
        // RulesRoots* rulesR = new RulesRoots;
        // rulesR->levels = new Levels;
        // // Leaf* ruleRoot = new Leaf;
        // Characters* rule = new Characters;
        // // for (int i = 0; i < ((*rIter).first)->size(); i++) {
        // // rule->push_back(((*rIter).first)->at(i));
        // // }
        // rule->assign(((*rIter).first)->begin(), ((*rIter).first)->end());
        // this->buildTree(rule, rulesR->rulesRoots, NULL, rulesR->levels);
        // // delete rule;
        // RulesRoots* rulesResult = new RulesRoots;
        // rulesResult->levels = new Levels;
        // // Leaf* ruleResultRoot = new Leaf;
        // // levels->clear();
        // rule->clear();
        ////            rule = new Characters;
        // rule->assign(((*rIter).second)->begin(), ((*rIter).second)->end());
        // // for (int i = 0; i < ((*rIter).second)->size(); i++) {
        // // rule->push_back(((*rIter).second)->at(i));
        // // }
        // this->buildTree(rule, rulesResult->rulesRoots, NULL,
        // rulesResult->levels);
        // // delete rule;
        // (rulesRoots)[rulesR] = rulesResult;
        // // rules->erase(rIter);
        // // delete rIter;
        // // delete rulesR;
        // // delete rulesResult;
        ////            delete((*rIter).first);
        // }
}

void BFIExpression::processRules(Characters* ruleIn, Characters* ruleResultIn) {
        RulesRoots* rulesR = new RulesRoots;
        rulesR->rulesRoots = new Leaf;
        rulesR->levels = new Levels;
        // Leaf* ruleRoot = new Leaf;
        Characters* rule = new Characters;
        // for (int i = 0; i < ((*rIter).first)->size(); i++) {
        // rule->push_back(((*rIter).first)->at(i));
        // }
        rule->assign(ruleIn->begin(), ruleIn->end());
        this->buildTree(rule, rulesR->rulesRoots, NULL, rulesR->levels);
        // delete rule;
        RulesRoots* rulesResult = new RulesRoots;
        rulesResult->rulesRoots = new Leaf;
        rulesResult->levels = new Levels;
        // Leaf* ruleResultRoot = new Leaf;
        // levels->clear();
        // rule->clear();
        Characters* rule1 = new Characters;
        // rule = new Characters;
        rule1->assign((ruleResultIn->begin()), (ruleResultIn->end()));
        // for (int i = 0; i < ((*rIter).second)->size(); i++) {
        // rule->push_back(((*rIter).second)->at(i));
        // }
        this->buildTree(rule1, rulesResult->rulesRoots, NULL, rulesResult->levels);
        // delete rule;
        (*rulesRoots)[rulesR] = rulesResult;
        // rules->erase(rIter);
        // delete rIter;
        // delete rulesR;
        // delete rulesResult;
        // delete((*rIter).first);

}

bool BFIExpression::equalVectors(Characters vector1, Characters vector2) {
        if (vector1.size() != vector2.size()) {
                return false;
        }
        for (int i = 0; i < vector1.size(); i++) {
                if (vector1[i]->key != vector2[i]->key ||
                        vector1[i]->inversion != vector2[i]->inversion) {
                        return false;
                }
        }
        return true;
}

bool BFIExpression::divideCharacters(Characters::iterator start,
        Characters::iterator end, Leaf* part1, Leaf* part2, bool divUnderInversion)
{

}

bool BFIExpression::trimBrackets(Characters* vector, iCharacters start,
        iCharacters end) {
		if ((*start)->key == "(") {
                int n = 1;
                bool trim = true;
                for (iCharacters i = start + 1; i <= end; i++) {
                        if ((*i)->key == "(") {
                                n++;
                        }
                        else if ((*i)->key == ")") {
                                n--;
                        }
                        if (n == 0 && i != end) {
                                trim = false;
                                // return;
                                break;
                        }
                }
                if (n != 0) {
                        trim = false;
                }
                if (trim) {
                        vector->erase(end);
                        vector->erase(start);
                        // end--;

                }
                return trim;
        }
        return false;
}

void BFIExpression::buildTree(Characters* vector, Leaf* root, Leaf* parent,
        Levels* levels, bool parseInversions) {
        this->buildTreeSimple(vector,root,parent,levels,parseInversions);
}

void BFIExpression::buildTreeSequence(Characters* vector, Leaf* root, Leaf* parent,
        Levels* levels, bool parseInversions) {
        Levels* newLevels = this->copyLevels(levels);
        if (count >= 178) {
                count = count;
        }
        if (!vector->empty()) {
				/*Form1->Memo1->Lines->Add("--------");
				if (count < 0) {
						for (iCharacters i = vector->begin(); i != vector->end(); i++) {
								Form1->Memo1->Lines->Add((*i)->key);
						}
			}     */

				this->buildTreeSimple(vector,root,parent,levels,parseInversions);
/*				Form1->Memo1->Lines->Add("--------");
				if (count < 0) {
						for (iCharacters i = root->start; i != root->end+1; i++) {
								Form1->Memo1->Lines->Add((*i)->key);
						}
						}                                                          */
				Characters* newChars = this->treeToCharacters(levels);
				//this->copyCharacters(root->start,root->end);
				if (!newChars->empty()) {
//              vector = newChars;
				this->buildTreeSimple(newChars,root,parent,newLevels,parseInversions);
				levels = this->copyLevels(newLevels);

                }
        }
}

Levels* BFIExpression::copyLevels(Levels* toCopy)
{
        Levels* levels = new Levels;
        for (int i = 0; i < toCopy->size(); i++) {
                (*levels)[i] = (*toCopy)[i];
        }
        return levels;
}


void BFIExpression::buildTreeSimple(Characters* vector, Leaf* root, Leaf* parent,
		Levels* levels, bool parseInversions) {

        int level = parent == NULL ? -1 : parent->level;
        root->level = level + 1;
        Leafs* vec;
        if (!(*levels).count(root->level)) {
                vec = new Leafs;
        }
        else
                vec = (*levels)[root->level];
        vec->push_back(root);
        (*levels)[root->level] = vec;
        count++;
        iCharacters begin = vector->begin();
        String k = (*begin)->key;
        root->start = begin;
        (*begin)->key = k;
        root->end = vector->end() - 1;
        root->right = NULL;
        root->left = NULL;
        root->parent = parent;
        root->i = NULL;
        Characters* vectorNew;
        vectorNew = new Characters;
        /* for (iCharacters i = vector->begin(); i < vector->end(); i++) {
         BooleanCharacter* character = new BooleanCharacter;
         character->inversion = (*i)->inversion;
         character->x = (*i)->x;
         character->y = (*i)->y;
         character->key = (*i)->key;
         vectorNew->push_back(character);
         } */
        // delete vector;
        iCharacters start = vector->begin();
        iCharacters end = vector->end();
        end--;
        bool flag = true;
        bool wasTrimmed = false;
        while (flag) {
                flag = trimBrackets(vector, start, end);
                if (flag) {
                        wasTrimmed = true;
                        start = vector->begin();
                        end = vector->end();
                        end--;

                }
        }
	    root->end = end;
        vectorNew = this->copyCharacters(vector->begin(), vector->end() - 1);
        iCharacters key;
		if ((key = this->findSeparator("or", start, end)) == NULL) {
				key = this->findSeparator("and", start, end);
		}

		if (key == NULL) {
			if ((key = this->findSeparator("or", start, end, true)) == NULL) {
					key = this->findSeparator("and", start, end, true);
			}
			
		}
		
				bool isInversed = false;

		if (key != NULL) {
				int i = (*key)->key == "or" ? 0 : 1;
				if (this->inversedSequence(vectorNew)) {
					isInversed = true;
					i = 1 - i;					
				}
				root->i = i;
				Characters* left = new Characters;
				// for (iCharacters i = start; i < key; i++) {
				// BooleanCharacter* character = new BooleanCharacter();
				// character->inversion = (*i)->inversion;
				// character->x = (*i)->x;
				// character->y = (*i)->y;
				// character->key = (*i)->key;
				//
				// left->push_back((character));
				// }
				left->insert(left->end(), start, key);
				Characters* newCharsBrackets = new Characters;
				newCharsBrackets = this->copyCharacters(left->begin(),left->end()-1);
				root->leftBrackets =
						this->trimBrackets(newCharsBrackets,newCharsBrackets->begin(),
						newCharsBrackets->end()-1);
				Characters* right = new Characters;
				// for (iCharacters i = key+1; i <= end; i++) {
				// BooleanCharacter* character = new BooleanCharacter();
                // character->inversion = (*i)->inversion;
                // character->x = (*i)->x;
                // character->y = (*i)->y;
                // character->key = (*i)->key;
                //
                // right.push_back((character));
                // }
                right->insert(right->end(), key + 1, end + 1);
                // root->left->parent = root;
                // root->right->parent = root;
                newCharsBrackets->clear();
                newCharsBrackets = this->copyCharacters(right->begin(),right->end()-1);
                root->rightBrackets =
                        this->trimBrackets(newCharsBrackets,newCharsBrackets->begin(),
                        newCharsBrackets->end()-1);
                root->left = new Leaf;
                root->right = new Leaf;
                if (!left->empty()) {
						buildTreeSimple(left, root->left, root, levels);
                }
                if (!right->empty()) {
                        buildTreeSimple(right, root->right, root, levels);
                }
                // delete left;
                // delete right;
		}

        this->createIterators(root);
		
		if (isInversed/* && root->right != NULL*/) {
					  this->reloadTreeToRoot(root);
		}
		
				if (parent != NULL &&
						parent->left != NULL &&
						parent->right != NULL &&
						parent->left->end != NULL &&
						parent->right->end != NULL &&
						parent->left->start != NULL &&
						parent->right->start != NULL
						&& ((parent->i == parent->right->i && /*parent->right->right != NULL
						&& parent->right->left != NULL)
						|| ( */parent->left->i == parent->i/*  && parent->left->right != NULL
						&& parent->left->left != NULL*/))
						&& (parent->leftBrackets || parent->rightBrackets)
						) {
								this->reloadTreeToRoot(root);

        }

        // delete vectorNew;
}

iCharacters BFIExpression::findSeparator(String key, iCharacters begin,
        iCharacters end, bool returnInversion) {
        for (iCharacters i = begin; i <= end; i++) {
                if ((*i)->key == "(") {
                        int n = 1;
                        i++;
                        while (n > 0 && i <= end) {
                                if ((*i)->key == "(") {
                                        n++;
                                }
                                if ((*i)->key == ")") {
                                        n--;
                                }
                                i++;
                        }
                        i--;
                        if (n != 0 && i == end) {
                                return NULL;
                        }
                }
				else if ((*i)->key == key) {
				if (!returnInversion &&  (*i)->inversion) {
                    continue;
				}
						return i;
                }
        }
        return NULL;
}

BFIExpression* BFIExpression::perform() {
        bool toPerform = true;
		root = new Leaf;
        Characters* chars = new Characters;
		chars = this->copyCharacters(this->characters.begin(),
				this->characters.end() - 1);
				int counter = 0;
		while (toPerform) {
			if (counter > 100) {
                break;
			}
			Levels* levels = new Levels;
			count = -100;
			this->buildTreeSequence(chars /* &this->characters */ , root, NULL, levels);
			int n = levels->size();
            chars = this->treeToCharacters(levels);


			for (int i = 0; i < n; i++) {
				Leafs* leafs = (*levels)[i];
				int leafsN = leafs->size();
				for (int j = 0; j < leafsN; j++) {
					Leaf* leaf = (*leafs)[j];
					Leaf* parent = leaf->parent;
					if (parent != NULL) {
						if (this->equalLeavesContent(leaf,parent->left)) {
							parent->left = leaf;
						}
						else if (this->equalLeavesContent(leaf,parent->right)) {
						{
							parent->right = leaf;
						}
					}
						}
				}
			}
			for (int i = 0; i < chars->size(); i++) {
				Form1->Memo1->Lines->Add((*chars)[i]->key);
			}
			Form1->Memo1->Lines->Add("--");
			bool breakedLevel = false;
			bool breaked = false;
			// Ð³âí³
			for (int i = 0; i < n; i++) {
				breaked = false;
				bool breakedTmp = false;
				breakedLevel = false;
				Leafs* leafs = (*levels)[i];
				// Âóçëè íà ð³âí³
				for (iLeafs iLeaf = leafs->begin(); iLeaf != leafs->end(); iLeaf++)
				{
					// Øàáëîíè
					int rulesCounter = 0;
					for (iRulesMap iMap = rulesRoots->begin();
					iMap != rulesRoots->end(); iMap++) {
						counter++;
						rulesCounter++;
						if (rulesCounter == 11) {
								rulesCounter = rulesCounter;
						}
						Leaf* tmp = ((*iMap).first)->rulesRoots;
						Net* net = new Net;
						this->initRelations(net);
						Leaf* l = (*iLeaf);
						if (this->equalLeaves(tmp, l, net)) {
							for (iCharacters i = l->start; i <= l->end; i++) {
								Form1->Memo1->Lines->Add((*i)->key);
							}
							Form1->Memo1->Lines->Add("----------");
							for (iCharacters i = tmp->start; i <= tmp->end; i++) {
								Form1->Memo1->Lines->Add((*i)->key);
							}
							Form1->Memo1->Lines->Add("------------------");

							for (iNet i = net->begin(); i != net->end(); i++) {
								Form1->Memo1->Lines->Add(((*i).first)->key);
								Form1->Memo1->Lines->Add("--");
								for (iCharacters it = (*i).second->begin(); 
								it < (*i).second->end(); it++) {
									Form1->Memo1->Lines->Add((*it)->key);
								}
								
							}
							Form1->Memo1->Lines->Add("------------------");
							Form1->Memo1->Lines->Add("------------------");

							Leaf* tmpResult = ((*iMap).second)->rulesRoots;
							Levels* levelsResult = ((*iMap).second)->levels;
							int levelsAmount = levelsResult->size();
							Leaf* newLeaf =
									this->rebuildLeaf(tmpResult, (*iLeaf)->level, net);
							Leaf* parent = (*iLeaf)->parent;
							if (parent != NULL) {
								newLeaf->parent = parent;
								if (parent->left == (*iLeaf)) {
										parent->left = newLeaf;
								}
								else if (parent->right == (*iLeaf)) {
										parent->right = newLeaf;
								} else if (this->equalLeavesContent(parent->left,(*iLeaf))) {
										parent->left = newLeaf;
									   }
								else if (this->equalLeavesContent(parent->right,(*iLeaf))) {
									parent->right = newLeaf;
							   }
                                parent = this->createIterators(parent);
								}

								root = reloadTreeToRoot(newLeaf);

//							   	root = this->createIterators(root);
								chars = this->copyCharacters(root->start, root->end);

								/*for (iCharacters i = root->start; i != root->end; i++) {
									BooleanCharacter* c = (*i);
									int gg =90;
								}*/

								breaked = true;
								breakedTmp = true;
								break;
							}
						}
						if (breaked && breakedTmp) {
								breakedLevel = true;
								break;
						}
					}
					// perform = false;
					if (breaked && breakedLevel) {
							break;
					}
					// toPerform = false;
			}
			if (!breaked) {
					toPerform = false;
			}

			// for (int j = n; j > 0; j--) {
			// Leafs* leafs = (*levels)[j - 1];
			// for (iLeafs i = leafs->begin(); i < leafs->end(); i += 2) {
			// for (iRulesMap iMap = rulesRoots->begin(); iMap != rulesRoots->end();
			// iMap++) {
			// Levels* levelsMap = ((*iMap).first)->levels;
			// int nMap = levelsMap->size();
			// Leafs* leafsMap = (*levelsMap)[nMap - 1];
			// for (iLeafs iLeafRules = leafsMap->begin();
			// iLeafRules < leafsMap->end(); iLeafRules += 2) {
			// map<BooleanCharacter*, Characters*> net;
			// if ((*iLeafRules)->parent != NULL && (*i)->parent != NULL &&
			// (*iLeafRules)->parent->i != NULL && (*i)->parent->i != NULL) {
			// if ((*iLeafRules)->parent->i == (*i)->parent->i) {
			// Characters* chars = new Characters;
			// chars->assign((*i)->start, (*i)->end);
			// net[(*(*iLeafRules)->start)] = chars;
			// if (equalLeaves((*i), (*iLeafRules), &net)) {
			// for (iCharacters iChar = (*iLeafRules)->start;
			// iChar != (*iLeafRules)->end; iChar++) {
			// Form1->Memo1->Lines->Add((*iChar)->key);
			// }
			//
			// }
			// }
			// }
			// else
			// {
			// if (equalLeaves((*i), (*iLeafRules), &net)) {
			// this->simplifyLeaf((*i),(*iMap).first->rulesRoots,
			// (*iMap).second->rulesRoots, &net);
			// }
			// }
			// }
			// }
			// }
			// }

			// perform = false;

        }
        // this-
        BFIExpression* exp = new BFIExpression(this->image, this->scrollBox);
        Characters* charsOut = new Characters;
        if (root->start != NULL && root->end != NULL) {
                charsOut->assign(root->start, root->end + 1);
        }
        exp->setCharacters(chars);
        return exp; // NULL;//new BFIExpression(this->image,this->scrollBox);
}

bool BFIExpression::equalLeavesContent(Leaf* leaf1, Leaf* leaf2)
{
	Characters* char1 = this->copyCharacters(leaf1->start,leaf1->end);
	Characters* char2 = this->copyCharacters(leaf2->start,leaf2->end);
	return this->equalSequences(char1,char2);
}

void BFIExpression::setCharacters(Characters* chars) {
        this->characters.clear();
        for (int i = 0; i < chars->size(); i++) {
                characters.push_back(chars->at(i));
        }
}

Leaf* BFIExpression::reloadTreeToRoot(Leaf* newLeaf) {

		Leaf* parent = newLeaf;
				this->charactersFromLeaf(parent);
		while (parent->parent != NULL) {
				parent = parent->parent;
/*				Characters* sequence = new Characters;
				addToCharacters(sequence, parent->left->start, parent->left->end);
				BooleanCharacter* operation = new BooleanCharacter;
				operation->inversion = false;
				operation->key = operationByID(parent->i);
				sequence->push_back(operation);
				addToCharacters(sequence, parent->right->start, parent->right->end);
				parent->start = sequence->begin();
				parent->end = sequence->end() - 1;*/
				this->charactersFromLeaf(parent);
		} /*
		if (parent->parent == NULL) {
			return parent;
		}
		else
		{
				parent = parent->parent;
				Characters* sequence = new Characters;
				addToCharacters(sequence, parent->left->start, parent->left->end);
				BooleanCharacter* operation = new BooleanCharacter;
				operation->inversion = false;
				operation->key = operationByID(parent->i);
				sequence->push_back(operation);
				addToCharacters(sequence, parent->right->start, parent->right->end);
				parent->start = sequence->begin();
				parent->end = sequence->end() - 1;
				parent = reloadTreeToRoot(parent);
		}   */
		return parent;

}

Leaf* BFIExpression::createLeafIterators(Leaf* newLeaf) {

        Leaf* parent = newLeaf;
        if (parent->left != NULL && parent->right != NULL) {
                Characters* sequence = new Characters;
                addToCharacters(sequence, parent->left->start, parent->left->end);
                BooleanCharacter* operation = new BooleanCharacter;
                operation->inversion = false;
                operation->key = operationByID(parent->i);
                sequence->push_back(operation);
                addToCharacters(sequence, parent->right->start, parent->right->end);
                parent->start = sequence->begin();
                parent->end = sequence->end() - 1;
    }
        return parent;
}


Leaf* BFIExpression::rebuildLeaf(Leaf* leaf, int level, Net* relations) {
        Leaf* result = new Leaf;
        if (leaf->right != NULL || leaf->left != NULL) {
                result->right = rebuildLeaf(leaf->right, level, relations);
                result->left = rebuildLeaf(leaf->left, level, relations);

        }
        else {
                result->right = NULL;
                result->left = NULL;

        }
        result->i = leaf->i;
        int levelPlus = leaf->level == NULL ? 0 : leaf->level;
        result->level = level + levelPlus;
        if (result->right != NULL && result->left != NULL) {
                Characters* sequence = new Characters;
                addToCharacters(sequence, result->left->start, result->left->end);
                BooleanCharacter* operation = new BooleanCharacter;
                operation->inversion = false;
                operation->key = operationByID(result->i);
                sequence->push_back(operation);
                addToCharacters(sequence, result->right->start, result->right->end);
                result->start = sequence->begin();
                result->end = sequence->end() - 1;
        }
        else {
                Characters* chars = findInNet(*(leaf->start), relations);
                // (*relations)[*(leaf->start)];
                if (chars != NULL) {
                        result->start = chars->begin();
                        result->end = chars->end()-1;

                }
                else {
                        result->start = NULL;
                        result->end = NULL;

                }
        }
        return result;

}

void BFIExpression::initRelations(Net* net) {
        BooleanCharacter* empty = new BooleanCharacter();
        empty->inversion = false;
        empty->key = "empty_set";
        BooleanCharacter* notEmpty = new BooleanCharacter();
        notEmpty->inversion = true;
        notEmpty->key = "empty_set";
        BooleanCharacter* universum = new BooleanCharacter();
        universum->inversion = false;
        universum->key = "U";
        BooleanCharacter* notUniversum = new BooleanCharacter();
        notUniversum->inversion = true;
        notUniversum->key = "U";
        net->clear();
        Characters* chars = new Characters;
        chars->push_back(empty);
        (*net)[empty] = chars;
        Characters* chars2 = new Characters;
        chars2->push_back(notEmpty);
        (*net)[notEmpty] = chars2;
        Characters* chars3 = new Characters;
        chars3->push_back(universum);
        (*net)[universum] = chars3;
        Characters* chars4 = new Characters;
        chars4->push_back(notUniversum);
        (*net)[notUniversum] = chars4;

        chars->clear();
}

void BFIExpression::addToCharacters(Characters* characters, iCharacters start,
        iCharacters end) {
        for (iCharacters i = start; i <= end; i++) {
                if (i == NULL) {
            return;
                }
                if ((*i) == NULL) {
                        return;
                }
                BooleanCharacter* char1 = new BooleanCharacter;
                char1->inversion = (*i)->inversion;
                char1->key = (*i)->key;
                char1->x = (*i)->x;
                char1->y = (*i)->y;
                characters->push_back(char1);
        }
}

String BFIExpression::operationByID(int id) {
        switch (id) {
        case 0:
                return "or";
        default:
                return "and";
        }
}

// bool BFIExpression::isKey(String key)
// {
// vector<String> keys;
// keys.push_back("and");
// keys.push_back("conv_implication");
// keys.push_back("empty_set");
// keys.push_back("implication");
// keys.push_back("or");
// keys.push_back("pirs");
// keys.push_back("text_symbol");
// keys.push_back("xor");
// keys.push_back("~");
// keys.push_back("|");
// }

bool BFIExpression::equalLeaves(Leaf* rule,
        // leaf* resultRule,
		Leaf* sequence, Net* relations
		, bool cloneRelations
		// ,    bool replace
        ) {
        if (rule->i != NULL && sequence->i != NULL && rule->i != sequence->i) {
                return false;
        }
        if (sequence == NULL) {
                return false;
        }
		if (rule->i != sequence->i) {
                return false;
        }
        bool result = false;
        if (rule->right == NULL && rule->left == NULL) {
                Characters* chars = new Characters;
                this->addToCharacters(chars, sequence->start, sequence->end);
                BooleanCharacter* key = *(rule->start);
				BooleanCharacter* keyForSequence = new BooleanCharacter;
                keyForSequence = this->inverseCharacter(key);
                // keyForSequence->inversion = true;
                // if (key->inversion) {
                // key->inversion = false;
                // }
                // if (relations->count(key)) {
                // Characters* c = (*relations)[key];
                // }
                // Net* net = relations;
                //
                // Characters* c;
                // for (iNet i = net->begin(); i != net->end(); i++) {
                // BooleanCharacter* key1 = (*i).first;
                // if (key1->key == "U" && key1->inversion == false) {
                ////                    (*net)[key] = (*net)[key1];
                // c =(*i).second/*(*net)[key]*/;
                // }
                // }

                if (keyInNet(key, relations) || keyInNet(keyForSequence, relations)
                        /* relations->count(*(rule->start)) */) {
                        Characters* toFind = findInNet(key, relations);
                        if (toFind == NULL) {
                                toFind = findInNet(keyForSequence, relations);
                                if (toFind != NULL) {
                                        toFind = this->inverseCharacters(toFind);
                                }
                        }
                        if (toFind == NULL) {
                                return false;
                        }
                        int nn = toFind->size();
                        if (this->equalSequences(chars, toFind)
                                /* (*relations)[keyForSequence] */) {
                                // return true;
                                result = true;
                        }
                        else
                                return false;
                }
                else {

                        if (!this->relationsContainSequence(chars, relations)) {
                                (*relations)[*(rule->start)] = chars;
                                // return true;
                                result = true;

							}
						else
								return false;
				}
		}
		else {
				if (sequence->left != NULL && sequence->right != NULL) {

						Net* net = this->cloneNet(relations);
						bool left = equalLeaves(rule->left, sequence->left, relations,true);
//						this->addToNet(relations,net);
//						net = this->cloneNet(relations);
						bool right = equalLeaves(rule->right, sequence->right, relations,true);
//						this->addToNet(relations,net);
						/* bool */ result = left && right;
						if (!result) {

//						if (!cloneRelations) {
//								relations->clear();
//								this->initRelations(relations);
//						} else
								relations = this->cloneNet(net);
								left = equalLeaves(rule->right, sequence->left, relations,true);
//								this->addToNet(relations,net);
								right = equalLeaves(rule->left, sequence->right, relations,true);
								result = left && right;
								if (result) {
										Leaf l = *(sequence->left);
										*(sequence->left) = *(sequence->right);
										*(sequence->right) = l;
								}
						}
						if (!result) {
							relations = this->cloneNet(net);							
						}
				}
		}
		// if (replace && result) {
		// Characters* sRight = this->copyCharacters(sequence->right->start,
		// sequence->right->start);
		// Characters* sLeft = this->copyCharacters(sequence->left->start,
		// sequence->left->start);
		// rule->left->start = sLeft->begin();
		// rule->left->end = sLeft->end()-1;
		// rule->right->start = sRight->begin();
        // rule->right->end = sRight->end()-1;
        // }

        return result;

}

Characters* BFIExpression::findInNet(BooleanCharacter* key, Net* net) {
        /* if (net->count(key)) {
         Characters* c = (*net)[key];
         return (*net)[key];
         } */
        for (iNet i = net->begin(); i != net->end(); i++) {
                BooleanCharacter* key1 = (*i).first;
                if (key1->key == key->key && key1->inversion == key->inversion) {
                        // (*net)[key] = (*net)[key1];
                        Characters* ñ = this->copyCharacters(((*i).second)->begin(),
                                ((*i).second)->end() - 1);
                        int nn = ñ->size();
                        if (nn == 0) {
                                ñ->push_back(*((*i).second)->begin());
                        }
                        return ñ /* (*net)[key] */ ;
                }
        }
        /* for (iNet i = net->begin(); i != net->end(); i++) {
         BooleanCharacter* key1 = (*i).first;
         if (key1->key == key->key && key1->inversion != key->inversion) {
         return this->inverseCharacters((*net)[key1]);
         }
         } */
        return NULL; // new Characters;
}

bool BFIExpression::keyInNet(BooleanCharacter* key, Net* net) {
        if (net->count(key)) {
                return true;
        }
        for (iNet i = net->begin(); i != net->end(); i++) {
                BooleanCharacter* key1 = (*i).first;
                if (key1->key == key->key && key1->inversion == key->inversion) {
                        // (*net)[key] = (*net)[key1];
                        return true;
                }
        }
        return false;
}

Characters* BFIExpression::copyCharacters(iCharacters start, iCharacters end) {
        Characters* chars = new Characters;
		for (iCharacters i = start; i <= end; i++) {
				if (i != NULL && (*i) != NULL) {
						BooleanCharacter* bChar = new BooleanCharacter;
						bChar->inversion = (*i)->inversion;
						bChar->key = (*i)->key;
						bChar->x = (*i)->x;
						bChar->y = (*i)->y;
						chars->push_back(bChar);
                } else break;
        }
        return chars;
}

Leaf* BFIExpression::createIterators(Leaf* leaf)
{
	Leaf* result = leaf;
/*	if (leaf->right != NULL) {
		Characters* char1 = new Characters;
		char1 = this->copyCharacters(leaf->left->start, leaf->left->end)	;
		BooleanCharacter* op = new BooleanCharacter;
		op->inversion = false;
		op->key = this->operationByID(leaf->i);
		char1->push_back(op);
		Characters* char2 = new Characters;
//		char1 = this->copyCharacters(leaf->right->start, leaf->right->end);
		this->addToCharacters(char1, leaf->right->start, leaf->right->end);
//				root->start = newC->begin();
//				root->end = newC->end() - 1;
//		Characters* char1 = new Characters;
//		this->copyCharacters(leaf->left->start, leaf->right->end)	;
		result->start = char1->begin();
		result->end = char1->end()-1;
	}*/
	this->charactersFromLeaf(result);
	return result;	
}
				
bool BFIExpression::equalCharacters(BooleanCharacter* char1,
        BooleanCharacter* char2) {
        return (char1->key == char2->key && char1->inversion == char2->inversion);
}

bool BFIExpression::isCharacterInversed(BooleanCharacter* char1,
        BooleanCharacter* char2) {
        return (char1->key == char2->key && char1->inversion != char2->inversion);
}

BooleanCharacter* BFIExpression::inverseCharacter(BooleanCharacter* char1,
        bool changeInParam) {
        BooleanCharacter* char2 = new BooleanCharacter;
        if (changeInParam) {
                char2 = char1;
        }
        char2->inversion = !(char1->inversion);
        char2->x = char1->x;
        char2->y = char1->y;
        char2->key = char1->key;
        return char2;
}

bool BFIExpression::equalSequences(Characters* char1, Characters* char2) {
        int c1 = char1->size();
        int c2 = char2->size();
        while (*(char1->end() - 1) == NULL) {
                char1->pop_back();
        }
        while (*(char2->end() - 1) == NULL) {
                char2->pop_back();
        }
        c1 = char1->size();
        c2 = char2->size();
        if (char1->size() != char2->size()) {
                return false;
        }
        bool equal = true;
        for (int i = 0; i < char1->size(); i++) {
                if (!equalCharacters(char1->at(i), char2->at(i)) /* (||
                         ((equalCharacters(char1->at(i), char2->at(i)))&&
                         char1->at(i)->inversion !=
                         char2->at(i)->inversion) */) {
                        equal = false;
                        break;
                }
        }
        return equal;
}

Characters BFIExpression::getCharacters() {
        return this->characters;
}

Characters* BFIExpression::getCharactersPointer() {
        return &this->characters;
}

void BFIExpression::simplifyLeaf(Leaf* leaf, Leaf* ruleTmp, Leaf* ruleResult,
        Net* relations) {

}

void BFIExpression::setImage(TImage* Image) {
        image = Image;
}

void BFIExpression::setScrollBox(TScrollBox* ScrollBox) {
        scrollBox = ScrollBox;
}

Characters* BFIExpression::addBrackets(Characters* chars)
{
	Characters* char2 = new Characters;
	BooleanCharacter* openBracket = new BooleanCharacter;
	openBracket->key = "(";
	openBracket->inversion = false;
	BooleanCharacter* closeBracket = new BooleanCharacter;
	closeBracket->key = ")";
	closeBracket->inversion = false;
	char2->push_back(openBracket);
	this->addToCharacters(char2, chars->begin(), chars->end()-1);
	char2->push_back(closeBracket);
	return char2;
}

Characters* BFIExpression::charactersFromLeaf(Leaf* leaf)
{
	Characters* chars = new Characters;
	if (leaf != NULL) {
		if (leaf->right != NULL && leaf->left != NULL) {
			Characters* left = new Characters;
			this->addToCharacters(left,leaf->left->start, leaf->left->end);
			Characters* right = new Characters;
			this->addToCharacters(right,leaf->right->start, leaf->right->end);
			if (leaf->i != 0) {
				if (leaf->right->left != NULL && leaf->right->right != NULL 
					&& leaf->right->i == 0 ) {
					right = this->addBrackets(right);
				}
				if (leaf->left->left != NULL && leaf->left->right != NULL 
					&& leaf->left->i == 0 ) {
					left = this->addBrackets(left);
				}
			}
			this->addToCharacters(chars,left->begin(),left->end()-1);
			BooleanCharacter* op = new BooleanCharacter;
			op->inversion = false;
			op->key = this->operationByID(leaf->i);
			chars->push_back(op);
			this->addToCharacters(chars,right->begin(),right->end()-1);
			leaf->start = chars->begin();
			leaf->end = chars->end()-1;
		} else
		this->addToCharacters(chars,leaf->start,leaf->end);
	}
	return chars;
}

Characters* BFIExpression::treeToCharacters(Levels* levels)
{
	Characters* chars = new Characters;
	int n = levels->size();
	for (int i = n-2; i >= 0; i--) {
		Leafs* leafs = (*levels->find(i)).second;
		int leafsAmount = leafs->size();
		for (int j = 0; j < leafsAmount; j++) {
			Leaf* leaf = (*leafs)[j];
			if (leaf->left != NULL && leaf->right != NULL) {
				this->charactersFromLeaf(leaf);
				leaf->left->parent = leaf;
				leaf->right->parent = leaf;
			}
		}
	}
	chars = this->copyCharacters((*(*levels)[0])[0]->start,(*(*levels)[0])[0]->end);
    return chars;
}


void BFIExpression::drawCharacters() {
        clearImage();
        init();
        int n = characters.size();
        for (int i = 0; i < characters.size(); i++) {
                String Character = '0';
                BooleanCharacter *char1 = characters[i];
                if (char1 == NULL) {
                        break;
                }
                String key = characters[i]->key;
                if ((key).Length() == 1) {
                        Character = key;
                        key = "text_symbol";
                }
                this->addByKey(key, characters[i]->inversion, Character, false);
        }
}

void BFIExpression::clearImage() {
        image->Canvas->FillRect(Rect(0, 0, image->Width, image->Height));
}

Characters* BFIExpression::inverseCharacters(Characters* chars) {
        Characters* charsNew = new Characters;
        charsNew = this->copyCharacters(chars->begin(), chars->end() - 1);
        Leaf* root = new Leaf;
        Levels* levels = new Levels;
        this->buildTree(charsNew, root, NULL, levels);
        int n = levels->size();
        for (iLeafs i = (*levels)[n - 1]->begin();
        i != (*levels)[n - 1]->end(); i++) {
                Leaf* leaf = (*i);
                for (iCharacters iChar = leaf->start; iChar != leaf->end; iChar++) {
                        this->inverseCharacter((*(iChar)), true);
                }
        }
        inverseOperations(root);
        // Characters* charsNew = new Characters;
        // this->addToCharacters(charsNew,root->start,root->end);
        return charsNew;
}

void BFIExpression::inverseOperations(Leaf* root) {
        if (root->left != NULL && root->right != NULL) {
                root->i = 1 - root->i;
                inverseOperations(root->left);
				inverseOperations(root->right);
				Characters* newC = new Characters;
				this->addToCharacters(newC, root->left->start, root->left->end);
				BooleanCharacter* op = new BooleanCharacter;
				op->inversion = false;
				op->key = this->operationByID(root->i);
				this->addToCharacters(newC, root->right->start, root->right->end);
				root->start = newC->begin();
				root->end = newC->end() - 1;
        }

}

void BFIExpression::backSpace() {
        if (!characters.empty()) {
                iCharacters i = characters.end();
                i--;
                BooleanCharacter* bc = (*i);
                String key = bc->key;
                if (key.Length() == 1) {
                        key = "text_symbol";
                }
                BFISymbol* symbol = BFISymbolsFactory::getSymbol(key,
                        this->image->Canvas, bc->inversion);

                int x = bc->x;
                int y = bc->y;
                int y_bot = y + image->Canvas->Font->Size * 2;
                int width = symbol->width();
                image->Canvas->FillRect(Rect(x - width - image->Canvas->Font->Size / 5,
                        y, x, y_bot));
                characters.erase(i);
                if (!characters.empty()) {
                        i = characters.end();
                        i--;
                        bc = (*i);
                        this->x = bc->x;
                        this->y = y;

                }
                else
                        init();
        }
}

bool BFIExpression::relationsContainSequence(Characters* sequence, Net* net) {
        bool result = false;
        for (iNet i = net->begin(); i != net->end(); i++) {
                if (this->equalSequences(sequence, (*i).second)) {
                        result = true;
                        break;
                }
        }
        return result;
}

bool BFIExpression::inversedSequence(Characters* chars) {
        bool inversed = true;
        for (iCharacters iter = chars->begin(); iter < chars->end(); iter++) {
                if (!(*iter)->inversion) {
                        inversed = false;
                        break;
                }
        }
        return inversed;
}

Net* BFIExpression::cloneNet(Net* net)
{
	Net* result = new Net();
	this->initRelations(result);
	for (iNet i = net->begin(); i != net->end(); i++) {
		BooleanCharacter* key = (*i).first;
		(*result)[key] = (*i).second;
	}
	return result;
}

Net* BFIExpression::addToNet(Net* result,Net* subject)
{
	for (iNet i = subject->begin(); i != subject->end(); i++) {
		BooleanCharacter* key = (*i).first;
		(*result)[key] = (*i).second;
	}
	return result;
}

